package vip.sweet.sys.modular.user.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import vip.sweet.common.response.CommonPageResponse;
import vip.sweet.common.service.CommonFileService;
import vip.sweet.common.utils.MD5Util;
import vip.sweet.sys.modular.department.entity.Department;
import vip.sweet.sys.modular.department.service.DepartmentService;
import vip.sweet.sys.modular.resources.entity.Resources;
import vip.sweet.sys.modular.role.entity.Role;
import vip.sweet.sys.modular.user.entity.User;
import vip.sweet.sys.modular.user.mapper.UserMapper;
import vip.sweet.sys.modular.user.params.UserAddParams;
import vip.sweet.sys.modular.user.params.UserAuthorizedRolesParams;
import vip.sweet.sys.modular.user.params.UserPageParams;
import vip.sweet.sys.modular.user.service.UserService;
import vip.sweet.sys.modular.user.vo.UserInfo;

import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @author tianlianyin
 * @date 2024/11/9
 */
@Service
@Slf4j
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {
    @Resource
    private CommonFileService commonFileService;
    @Resource
    private DepartmentService departmentService;
    /**
     * 根据用户名查询用户角色
     * @param username 用户名
     * @return 角色列表
     */
    @Override
    public List<Role> getAllRolesByName(String username) {
        LambdaQueryWrapper<User> queryWrapper=new LambdaQueryWrapper<>();
        queryWrapper.eq(User::getUsername,username);
        return baseMapper.getAllRolesById(baseMapper.selectOne(queryWrapper).getId());
    }

    /**
     * 根据用户名查询用户资源
     * @param username  用户名
     * @return 资源列表
     */
    @Override
    public List<Resources> getAllResourceByName(String username) {
        LambdaQueryWrapper<User> queryWrapper=new LambdaQueryWrapper<>();
        queryWrapper.eq(User::getUsername,username);
        if (baseMapper.selectOne(queryWrapper)==null){
            return null;
        }
        return baseMapper.getAllResourceByName(baseMapper.selectOne(queryWrapper).getId());
    }

    @Override
    public List<Resources> getAllAuthByName(String username) {
        LambdaQueryWrapper<User> queryWrapper=new LambdaQueryWrapper<>();
        queryWrapper.eq(User::getUsername,username);
        if (baseMapper.selectOne(queryWrapper)==null){
            return null;
        }
        return baseMapper.getAllAuthByName(baseMapper.selectOne(queryWrapper).getId());
    }

    /**
     * 根据用户名查询用户信息
     * @param username 用户名
     * @return 用户信息
     */
    @Override
    public UserInfo getUserInfo(String username) {
        LambdaQueryWrapper<User> lambdaQueryWrapper=new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(User::getUsername,username);
        User user = getOne(lambdaQueryWrapper);
        List<Role> roleList=getAllRolesByName(user.getUsername());
        UserInfo userInfo=BeanUtil.toBean(user,UserInfo.class);
        List<Resources> resourcesList=getAllResourceByName(user.getUsername());
        List<Resources> resourcesVOS=resourcesList.stream().map(
                resources -> {
                    Resources resourceVO = new Resources();
                    BeanUtils.copyProperties(resources, resourceVO);
                    return resourceVO;
                }
        ).toList();
            userInfo.setRoles(roleList);
            userInfo.setResourceList(resourcesVOS.stream().filter(resourceVO -> resourceVO.getParentId().equals("top")).peek(menu -> menu.setChildren(getChildrenData(menu, resourcesVOS))).toList());
            userInfo.setRouters(resourcesList.stream().filter(resourceVO -> resourceVO.getType().equals("menu")).toList());
        return userInfo;
    }

    @Override
    public boolean add(UserAddParams user) {
        User addUser= BeanUtil.toBean(user,User.class);
        LambdaQueryWrapper<Department> lambdaQueryWrapperUser=new LambdaQueryWrapper<>();
        if (ObjectUtil.isNotEmpty(user.getDepartmentId()))
            lambdaQueryWrapperUser.eq(Department::getId,user.getDepartmentId());
        addUser.setDepartmentName(departmentService.getOne(lambdaQueryWrapperUser).getName());
        addUser.setPassword(MD5Util.getMD5String(user.getPassword()));
        LambdaQueryWrapper<User> lambdaQueryWrapper=new LambdaQueryWrapper<>();
        if (ObjectUtil.isNotEmpty(user.getUsername()))
            lambdaQueryWrapper.eq(User::getUsername,user.getUsername());
        if (ObjectUtil.isEmpty(getOne(lambdaQueryWrapper))){
            this.save(addUser);
            return true;
        }
        return false;
    }

    @Override
    public boolean delete(String id) {
        if(ObjectUtil.isNotEmpty(getById(id)))
            return removeById(id);
        return false;
    }

    @Override
    public boolean edit(User user) {
        LambdaQueryWrapper<Department> lambdaQueryWrapperUser=new LambdaQueryWrapper<>();
        if (ObjectUtil.isNotEmpty(user.getDepartmentId()))
            lambdaQueryWrapperUser.eq(Department::getId,user.getDepartmentId());
        user.setDepartmentName(departmentService.getOne(lambdaQueryWrapperUser).getName());
        if(ObjectUtil.isNotEmpty(getById(user.getId()))){
            return updateById(user);
        }
        return false;
    }

    @Override
    public boolean uploadAvatar(MultipartFile avatar) {
        Object context = SecurityContextHolder.getContext().getAuthentication().getPrincipal();
        String id = this.getOne(new LambdaQueryWrapper<User>().eq(User::getUsername, context)).getId();
        String objectName = "avatar/" + id+'-'+ DateUtil.format(new Date(), "yyyy-MM-dd-HH-mm-ss") + ".jpg";
        try {
            String avatarUrl = commonFileService.uploadFile(avatar, objectName);
            User user = getById(id);
            user.setAvatar(avatarUrl);
            return updateById(user);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return false;
    }

    @Override
    public CommonPageResponse pageList(UserPageParams userPageParams) {
        LambdaQueryWrapper<User> lambdaQueryWrapper=new LambdaQueryWrapper<>();
        if (ObjectUtil.isNotEmpty(userPageParams.getName()))
            lambdaQueryWrapper.like(User::getUsername,userPageParams.getName());
        if (ObjectUtil.isNotEmpty(userPageParams.getDepartmentId()))
            lambdaQueryWrapper.eq(User::getDepartmentId,userPageParams.getDepartmentId());
        Page<User> pageQuery = new Page<>(userPageParams.getPageNum(), userPageParams.getPageSize());
        Page<User> page = page(pageQuery, lambdaQueryWrapper);
        return CommonPageResponse.builder()
                .pageNum((int) page.getCurrent())
                .pageSize((int) page.getSize())
                .total( page.getTotal())
                .totalPages((int) page.getPages())
                .data(page.getRecords())
                .build();
    }

    @Override
    public boolean authorizedRoles(UserAuthorizedRolesParams userAuthorizedRolesParams) {
        baseMapper.clearAllRoles(userAuthorizedRolesParams.getUserId());
        log.error("userId:{},roleIds:{}",userAuthorizedRolesParams.getUserId(),userAuthorizedRolesParams.getRoleIds());
        return baseMapper.authorizedRoles(userAuthorizedRolesParams.getUserId(), userAuthorizedRolesParams.getRoleIds());
//        return true;
    }

    @Override
    public boolean exportInfo(String username) {
        LambdaQueryWrapper<User> lambdaQueryWrapper=new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(User::getUsername,username);
        User user = getOne(lambdaQueryWrapper);

        return true;
    }

    //获取孩子（下级目录）的方法，递归实现
    private List<Resources> getChildrenData(Resources root, List<Resources> all) {
        return all.stream().filter(subjectVO ->
                subjectVO.getParentId().equals(root.getId())
        ).peek(subjectVO -> subjectVO.setChildren(getChildrenData(subjectVO, all))).collect(Collectors.toList());
    }
}
